package com.android.lyricshow.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.android.lyricshow.bean.SongBean;
import com.android.lyricshow.until.LogPrint;

import android.util.Log;

/**
 * Resolver lyric from file
 * 
 */
public class LyricParser{
	/**
	 * The sentence list 
	 */
	private List<Sentence> mLrcList = new ArrayList<Sentence>();
	/**
	 * The song tag
	 */
	private SongTag mTagInfo 		= new SongTag();
	
	private SongBean mSong;
	
	public LyricParser(String lrcPath, SongBean sbean){
		this.mSong = sbean;
		init(new File(lrcPath));
	}
	
	private void init(File lrcFile){
		
		BufferedReader bReader	= null;
		
		try {
			bReader	= new BufferedReader(new FileReader(lrcFile));		
			init(bReader);
		} catch (FileNotFoundException e) {
			LogPrint.e(e);
		} finally {
			try {
				if(bReader != null) {
					bReader.close();
				}
			} catch (IOException e) {
				LogPrint.e(e);
			}	
		}
	}
	private void init(BufferedReader br){
		
		String temp = null;
		
		try {
			while((temp = br.readLine()) != null){
				parseLine(temp.trim());
			}
		} catch (Exception e) {
			LogPrint.e(e);
			return;
		}
	
		//sort by from time
		Collections.sort(mLrcList, new Comparator<Sentence>() {
			@Override
			public int compare(Sentence lhs, Sentence rhs) {
				return (int) (lhs.getFromTime() - rhs.getFromTime());
			}
		});
		
		//add to time
		int count = mLrcList.size();
		for(int i = 0; i < count; i++){
			
			long nexttime;
			if(i + 1 == count){
				nexttime = mSong.getTime(); 
			}else{
				nexttime = mLrcList.get(i + 1).getFromTime() - 1;
			}
			
			Sentence st = mLrcList.get(i);
			st.setToTime(nexttime);
		}
		
		if(count > 0){
			addTagInfo();
		}
	}
	
	private void addTagInfo(){
		
		for(int i = 0; i < 5 && i < mLrcList.size() - 1; i++){
			
			if(mLrcList.get(i).getContent().contains(mSong.getTitle())){
				return;
			}
		}
		
		long toTime	= mLrcList.get(0).getFromTime() - 1;
		mLrcList.add(0, new Sentence(mSong.getArtist() + "-" + mSong.getTitle(), 0, toTime));
	}
	
	private static final Pattern mTimePattern = Pattern.compile("(\\d{2}:\\d{2}\\.\\d{2})");
	
	private static final String TAG_TITLE	= "[ti:";
	private static final String TAG_AUTHOR	= "[ar:";
	private static final String TAG_ALBUM	= "[al:";
	private static final String TAG_EDITOR	= "[by:";
	private static final String TAG_OFFSET	= "[offset:";
	
	private void parseLine(String strSentence) throws Exception{
		
		if (strSentence.startsWith(TAG_TITLE)) {
			String title = strSentence.substring(TAG_TITLE.length(), strSentence.length() - 1);
			mTagInfo.setTitle(title);
		}else if(strSentence.startsWith(TAG_ALBUM)){
			String ablum = strSentence.substring(TAG_ALBUM.length(), strSentence.length() - 1);
			mTagInfo.setAlbum(ablum);
		}else if(strSentence.startsWith(TAG_AUTHOR)){
			String author = strSentence.substring(TAG_AUTHOR.length(), strSentence.length() - 1);
			mTagInfo.setAuthor(author);
		}else if(strSentence.startsWith(TAG_EDITOR)){
			String editor = strSentence.substring(TAG_EDITOR.length(), strSentence.length() - 1);
			mTagInfo.setEditor(editor);
		}else if(strSentence.startsWith(TAG_OFFSET)){
			String soffset = strSentence.substring(TAG_OFFSET.length(), strSentence.length() - 1);
			int offset = Integer.parseInt(soffset);
			mTagInfo.setOffset(offset);
		}else{
			
			Matcher matcher	= mTimePattern.matcher(strSentence);
			List<String> temp = new ArrayList<String>();
			
			int lastIndex = 0;
			while (matcher.find()) {
				
				String match = matcher.group();
				lastIndex = matcher.end() + 1;
				temp.add(match);
			}
			
			if(lastIndex > 0){
				String content = strSentence.substring(lastIndex);
				for(String s : temp){
					
					long time =  parseTime(s);
					if(-1 == time){
						continue;
					}
					
					Sentence st = new Sentence(content.trim(), time);
					mLrcList.add(st);
				}
			} 
		}
	}
	
	private static final String TIME_SPIT 	= "\\:|\\.";
	private static final int TIME_FORMAT_EX = 3;
	
	private long parseTime(String strtime){
		long ltime = -1;
		String[] time = strtime.split(TIME_SPIT);
		if(time.length == TIME_FORMAT_EX){
			int min	= Integer.parseInt(time[0]);
			int sec	= Integer.parseInt(time[1]);
			int mm	= Integer.parseInt(time[2]);
			
			if (min < 0 || sec < 0 || sec > 60 || mm < 0 || mm > 99) {
				throw new RuntimeException("Error time format");
			}
			
			ltime = (min * 60 + sec) * 1000L + mm * 10;
		}
		
		return ltime;
	}
	
	public int getNowSentenceIndex(long t) {
		int count = mLrcList.size();
		
		for (int i = 0; i < count; i++) {
			if (mLrcList.get(i).isInTime(t)) {
				return i;
			}
		}
		return -1;
	}
	
	public List<Sentence> getList(){
		return mLrcList;
	}
	
	public void printlist(){
		for(int i = 0; i < mLrcList.size(); i++){
			Sentence st = mLrcList.get(i);
			Log.e("Lyric", "(" + st.getFromTime() + ")" + st.getContent() + "(" + st.getToTime() + ")");
		}
	}
}
